/*
* lJavaScript	: Little JavaScript Parser v2.0
****************************************************
* Author	: CN.LEI
* Mail	: scriptpower@qq.com
* WebSite	: http://www.cnlei.com
* Created	: 2010-01-01
* Update	: 2010-01-23
****************************************************
* 1. 解析JavaScript语法
    分析JS代码中的纯代码、字符串、正则、注释等等对其进行归类，按序存入数组中，并返回该数组以供其它API接口使用。
* 2. 扩展功能：
    以此解析器的返回结果为基础，可方进行以下各种功能扩展和实现
    a. JS语法标亮着色、
    b. JS代码压缩合并、
    c. JSON数据安全检测
    d. 等等
****************************************************
* System.JavaScript.parse(jscode)
* @param
  jscode	: 待解析的JavaScript代码, String类型
* @return	:
  >> 格式:
  [code,flag,value,code,flag,value...,code,flag,value,code,-1,空串]
  即:
  [js,0,正则值,js,1,单引号字符串值,js,2,双引号字符串值,js,7,单行注释内容,js,8,多行注释内容,js]
  >> flag含义：
	1	: 单引号
	2	: 双引号
	3	: 正则
	7	: 单行注释
	8	: 多行注释
*/
(function (S){
	var testRegxPre=/[\,\=\?\:\&\!\(\[\;\|\+\-\*\%\~\<\>]\s*$|\b(?:return|typeof)\s*$/,//探测正则前缀
		//TYPE_NONE = 0,
		TYPE_Q1 = 1,	 //单引号字符串
		TYPE_Q2 = 2, //双引号字符串
		TYPE_REG = 3,	//正则
		TYPE_C1 = 7,	 //单行注释
		TYPE_C2 = 8,
		extend	= function (dest, src){
			for(var k in src) dest[k] = src[k];
			return dest;
		};	

	//getIdxEndOfFlag
	function getIdxEndOfFlag(string , flag , i , length){
		var n=-1,c;
		while(i++<length){
			c = string.charAt(i);
			if(c === flag){
				return i;
			} else if(c === "\\"){//跳过转义符号
				i++;
			}
		}
		return n;
	}

	//getIdxEndOfReg
	function getIdxEndOfReg(string,i,length){
		var end,idxZ;
		end = getIdxEndOfFlag(string,"\/",i,length);
		//idxZ=getIdxEndOfFlag(string,"\[",i,length);
		idxZ = getIdxEndOfFlag(string,"\[",i,end);
		//if(idxZ<0 || idxZ>end){//正则中无中括号
		if(idxZ < 0){//正则中无中括号
			return end;
		} else {//idxZ<end : 正则中有中括号
			idxZ=getIdxEndOfFlag(string,"\]",idxZ,length);
			if(idxZ < 0){//正则非法
				return -1;
			} else {//继续往后找
				return getIdxEndOfReg(string,idxZ,length);
			}
		}
	}
	
	//检测是否为正则表达式前缀标志
	function checkRegPreFlag(A,rjs){	//(arrParsed, sRightJS)
		var b=true,t, i;
		for(i = A.length-3 ; i>=0 ; i--){
			t = A[i+1];
			if( t >= TYPE_C1){//多行注释
				if(!/^\s*$/.test(A[i])){
					b = testRegxPre.test(A[i]);
					if(!b) b = /\/\s*$/.test(A[i]);//正则作为除数
					return b;
				}
			} else {
				b=!!rjs && /\/\s*$/.test(rjs);
				return b;
			}
		}
		return b;
	}
	
	//解释JS代码
	function parse(string){
		string=string.replace(/\r\n?/g,"\r\n");
		var i=0, length = string.length,end,last=0;
		var c,cr,ret=[],js,mode,tmp,value;
		var regStart=false;//正则特征检测
		var leftCode = [];

		for(i=0;i<length;){
			c=string.charAt(i);
			if(c=="\"" || c=="\'"){
				end=getIdxEndOfFlag(string,c,i,length);
				if(end>i){//找到字符串
					end++;
					js = string.substring(last,i);
					value = string.substring(i,end);
					ret.push(js,c=="\"" ? TYPE_Q2 : TYPE_Q1, value);
					i=last=end;
				} else {//字符串中断
					break;
				}
			} else if(c=="\/"){//注释、正则、除法
				cr=string.charAt(i+1);
				if(!cr)break;
				if(cr=="\/"){//单行注释
					end=string.indexOf("\r\n",i+2);
					if(end<0){
						end=length;
					} else {
						end+=2;
					}
					js = string.substring(last,i);
					value = string.substring(i,end);
					ret.push(js,TYPE_C1,value);
					i=last=end;
				} else if(cr=="*"){//多行注释
					end=string.indexOf("*\/",i+2);
					if(end>i){
						end+=2;
						js = string.substring(last,i);
						value = string.substring(i,end);
						ret.push(js,TYPE_C2, value);
						i=last=end;
					} else {//多行注释中断
						break;
					}
				} else {//正则、除法分析
					js=string.substring(last,i);
					regStart=false;
					if(testRegxPre.test(js)){//正则开始
						regStart=true;
					} else{ //if(/^\s*$/.test(js))
						if(/\/\s*$/.test(js)){//正则作为除数
							var retLen=ret.length;
							if(retLen>0){
								if(ret[retLen-2] == 8){
									regStart = checkRegPreFlag(ret,js); //向前查找特征符
								} else {
									regStart = true;
								}
							} else {
								regStart = true;
							}
						} else if(/^\s*$/.test(js)){//向前查找特征符
							regStart=checkRegPreFlag(ret,js);
						}
					}
					if(regStart){
						end=getIdxEndOfReg(string,i,length);
						if(end>i){//找到正则
							mode=string.substring(end,end+4);
							mode=mode.match(/^\/[igm]*/);
							mode=mode[0];
							ret.push(js,TYPE_REG,string.substring(i,end)+mode);
							i=last=end+mode.length;
							//i=end;
						} else {//正则中断
							break;
						}
					} else {//除法
						i++;
					}
				}//正则、除法分析 end
			} else if(c=="\\"){//转义符直接跳过
				i+=2;
			} else {
				i++;
			}
		}
		ret.push(string.substring(last,length));
		return ret;
	}

	function color(string, cfg){
		var parsed = parse(string),
			opt = extend({}, cfg);
	}

	S.define(S,
		"JavaScript",{}
	).define(S.JavaScript,
		"parse", parse,
		"color", color
	);

})(SP);